/*
 * Created on Mar 19, 2010
 */
package ro.letsdoitromania.forms;

import java.util.Date;
import java.util.Vector;
import javax.microedition.lcdui.*;
import ro.letsdoitromania.*;
import com.mgmaps.app.APPCommands;
import com.mgmaps.gps.GPSReceiver;
import com.mgmaps.tools.MiscTools;
import com.mgmaps.tools.UITools;
import com.mgmaps.utils.ExtLogger;
import com.mgmaps.utils.LS;
import com.nutiteq.components.WgsPoint;

public class AddEditForm implements CommandListener {
  private Form form;
  
  private StringItem siError;
  private TextField tfDesc;
  private Gauge gLength;
  private Gauge gWidth;
  private Gauge gHeight;
  // private ChoiceGroup cgRoadDifficult;
  private ChoiceGroup cgDispersed;
  private Gauge gBagEq;
  private StringItem siPerc;
  private Gauge[] gPerc;
  
  private static AddEditForm instance;
  private String language;
  private boolean editMode;
  
  private TrashPointData tpd;
  
  public static AddEditForm getInstance() {
    if (instance == null)
      instance = new AddEditForm();
    return instance;
  }
  
  private AddEditForm() {
    language = Settings.language;
  }
  
  private void resetForm() {
    siError = null;
    tfDesc = null;
    gLength = null;
    gWidth = null;
    gHeight = null;
    // cgRoadDifficult = null;
    cgDispersed = null;
    gBagEq = null;
    siPerc = null;
    gPerc = null;
  }
  
  public void showAdd() {
    editMode = false;
    show(null, true);
  }
  
  public void showEdit(TrashPointData p) {
    editMode = true;
    tpd = p;
    show(null);
  }
  
  public void show(String errmsg) {
    show(errmsg, false);
  }
  
  public void show(String errmsg, boolean reset) {
    if (language != Settings.language)
      resetForm();
    
    if (errmsg != null) {
      if (siError == null)
        siError = new StringItem(LS.get("app.form.error"), errmsg);
      else
        siError.setText(errmsg);
    }
    
    if (tfDesc == null)
      tfDesc = new TextField(LS.get("ldir.add.desc"), "", 250, TextField.ANY);
    
    if (gLength == null)
      gLength = new Gauge(LS.get("ldir.add.length"), true, 50, 1);
    
    if (gWidth == null)
      gWidth = new Gauge(LS.get("ldir.add.width"), true, 50, 1);
    
    if (gHeight == null)
      gHeight = new Gauge(LS.get("ldir.add.height"), true, 20, 0);
    
    // if (cgRoadDifficult == null)
    //   cgRoadDifficult = new ChoiceGroup(LS.get("ldir.add.roaddif"), Choice.MULTIPLE,
    //       new String[] { LS.get("ldir.add.roaddifall"), LS.get("ldir.add.roaddifrain") }, null);
    
    if (cgDispersed == null)
      cgDispersed = new ChoiceGroup(LS.get("ldir.add.disptitle"), Choice.MULTIPLE,
          new String[] { LS.get("ldir.add.dispersed") }, null);
    
    if (gBagEq == null)
      gBagEq = new Gauge(LS.get("ldir.add.bageq"), true, 50, 0);
    
    if (siPerc == null)
      siPerc = new StringItem("\n", LS.get("ldir.add.perc.header"));
    
    if (gPerc == null)
      gPerc = new Gauge[TrashPointData.NUM_PERCENTAGES];
    
    for (int i=0; i<TrashPointData.NUM_PERCENTAGES; i++)
      if (gPerc[i] == null)
        gPerc[i] = new Gauge(LS.get("ldir.add.perc." + i) + ":", true, 10, 0);
    
    Vector itemVector = new Vector();
    if (errmsg != null)
      itemVector.addElement(siError);
    itemVector.addElement(tfDesc);
    itemVector.addElement(gLength);
    itemVector.addElement(gWidth);
    itemVector.addElement(gHeight);
    // itemVector.addElement(cgRoadDifficult);
    itemVector.addElement(cgDispersed);
    itemVector.addElement(gBagEq);
    itemVector.addElement(siPerc);
    for (int i=0; i<TrashPointData.NUM_PERCENTAGES; i++)
      itemVector.addElement(gPerc[i]);
    
    final Item[] items = new Item[itemVector.size()];
    itemVector.copyInto(items);
    itemVector.removeAllElements();

    form = UITools.buildForm(form, LS.get(editMode ? "ldir.change.title" : "ldir.add.title"), items,
        new Command[] { APPCommands.instance.okCommand, APPCommands.instance.cancelCommand }, this);
    
    if (reset) {
      tfDesc.setString("");
      gLength.setValue(1);
      gWidth.setValue(1);
      gHeight.setValue(0);
      // cgRoadDifficult.setSelectedFlags(new boolean[] { false, false });
      cgDispersed.setSelectedFlags(new boolean[] { false });
      gBagEq.setValue(0);
      for (int i=0; i<TrashPointData.NUM_PERCENTAGES; i++)
        gPerc[i].setValue(0);
    }
    else if (editMode) {
      tfDesc.setString(tpd.getDescription());
      gLength.setValue((int) MiscTools.round(tpd.getLength()));
      gWidth.setValue((int) MiscTools.round(tpd.getWidth()));
      gHeight.setValue((int) MiscTools.round(tpd.getHeight()));
      // cgRoadDifficult.setSelectedFlags(new boolean[] { tpd.isRoadDifficult(), tpd.isRoadDifficultRain() });
      cgDispersed.setSelectedFlags(new boolean[] { tpd.isDispersed() });
      gBagEq.setValue((int) MiscTools.round(tpd.getBagEq()));
      int[] perc = tpd.getPercentages();
      for (int i=0; i<TrashPointData.NUM_PERCENTAGES; i++)
        gPerc[i].setValue((int) MiscTools.round(perc[i]/10.0));
    }
    
    Display.getDisplay(LDIRMidlet.instance).setCurrent(form);    
  }

  public void commandAction(Command cmd, Displayable d) {
    if (cmd == APPCommands.instance.okCommand) {
      if (!editMode) {
        // check that we have a GPS fix and it's recent, etc.
        String errmsg = getGPSErrorMessage();
        if (errmsg != null) {
          show(errmsg);
          return;
        }
      }

      if (tfDesc.getString().trim().length() == 0) {
        show(LS.get("ldir.add.errdesc"));
        return;
      }
      
      try {
        final String desc = tfDesc.getString().trim();
        final int length = gLength.getValue();
        final int width = gWidth.getValue();
        final int height = gHeight.getValue();
        final boolean dif = // cgRoadDifficult.isSelected(0);
          false;
        final boolean difRain = // cgRoadDifficult.isSelected(1);
          false;
        final boolean disp = cgDispersed.isSelected(0);
        final int bageq = gBagEq.getValue();
        final int[] perc = new int[TrashPointData.NUM_PERCENTAGES];
        for (int i=0; i<TrashPointData.NUM_PERCENTAGES; i++)
          perc[i] = gPerc[i].getValue()*10;

        if (!editMode) {
          // ok, build a TrashPointData object
          final int id = editMode ? tpd.getID() : Settings.points.size()+1;
          final Date dt = editMode ? tpd.getDateTime() : new Date();
          final WgsPoint point = editMode ? tpd.getPoint() : LDIRCanvas.instance.getGPSPlace().getWgs();
        
          tpd = new TrashPointData(id, dt, point, desc, length, width, height, dif, difRain, disp, bageq, perc);
        
          ViewForm.getInstance().show(tpd, LS.get("ldir.add.confirm"),
              new Command[] { Commands.cinstance.addCommand, Commands.instance.backCommand }, this);
        }
        else {
          tpd.setDescription(desc);
          tpd.setLength(length);
          tpd.setWidth(width);
          tpd.setHeight(height);
          tpd.setRoadDifficult(dif);
          tpd.setRoadDifficultRain(difRain);
          tpd.setDispersed(disp);
          tpd.setBagEq(bageq);
          tpd.setPercentages(perc);
          
          Settings.save();

          Display.getDisplay(LDIRMidlet.instance).setCurrent(ViewList.getInstance().getList());
          SerialCall.instance.show(SerialCall.SC_ALERT, LS.get("ldir.change.title"), LS.get("ldir.change.done"));
        }
      }
      catch (Exception ex) {
        ExtLogger.handle(ex, false, "Error saving trash point data");
        show(LS.get("ldir.add.error", new String[] { ex.getMessage() }));
      }
    }

    else if (cmd == Commands.cinstance.addCommand) {
      // all ok, add to array and save settings
      Settings.points.addElement(tpd);
      Settings.save();
      
      // return to main canvas
      Display.getDisplay(LDIRMidlet.instance).setCurrent(LDIRCanvas.instance);
      ViewForm.getInstance().getForm().deleteAll();
      SerialCall.instance.show(SerialCall.SC_ALERT, LS.get("ldir.add.title"), LS.get("ldir.add.done"));
    }
    else if (cmd == APPCommands.instance.backCommand) {
      if (editMode)
        Display.getDisplay(LDIRMidlet.instance).setCurrent(ViewList.getInstance().getList());
      else
        Display.getDisplay(LDIRMidlet.instance).setCurrent(form);
    }
    else if (cmd == APPCommands.instance.cancelCommand)
      Display.getDisplay(LDIRMidlet.instance).setCurrent(LDIRCanvas.instance);
  }

  /**
   * Get an error message if the GPS is not connected, or null if all is ok.
   * @return error message or null if all is ok.
   */
  private String getGPSErrorMessage() {
    GPSReceiver recv = LDIRCanvas.instance.getGPSReceiver();
    if (recv == null)
      return LS.get("gps.error.notavailable");
    if (!recv.isConnected())
      return LS.get("gps.error.notconnected");
    if (!recv.getHasFix())
      return LS.get("gps.error.nofix");
    if (System.currentTimeMillis() - recv.getFixTimeAdjusted() > Settings.GPS_VALIDITY_TIME)
      return LS.get("gps.error.fixtooold");
    if (LDIRCanvas.instance.getGPSPlace().getWgs() == null)
      return LS.get("gps.error.nofix");
    return null;
  }  
}
